package common

import (
	"fmt"
	"time"
)

// TimeZoneConfig 时区配置
type TimeZoneConfig struct {
	DefaultTimeZone  string `yaml:"default_timezone" json:"default_timezone"`
	DatabaseTimeZone string `yaml:"database_timezone" json:"database_timezone"`
	DisplayTimeZone  string `yaml:"display_timezone" json:"display_timezone"`
}

// GlobalTimeZone 全局时区配置
var GlobalTimeZone *TimeZoneConfig

// 常用时区映射
var TimeZoneMap = map[string]string{
	"UTC":  "UTC",
	"GMT":  "GMT",
	"EST":  "America/New_York",
	"PST":  "America/Los_Angeles",
	"CST":  "Asia/Shanghai",
	"HKT":  "Asia/Hong_Kong",
	"SGT":  "Asia/Singapore",
	"JST":  "Asia/Tokyo",
	"KST":  "Asia/Seoul",
	"IST":  "Asia/Kolkata",
	"WET":  "Europe/London",
	"CET":  "Europe/Paris",
	"EET":  "Europe/Athens",
	"MSK":  "Europe/Moscow",
	"SAST": "Africa/Johannesburg",
	"AEST": "Australia/Sydney",
	"NZST": "Pacific/Auckland",
}

// InitTimeZone 初始化时区配置
func InitTimeZone(config *TimeZoneConfig) error {
	if config == nil {
		// 使用默认配置
		config = &TimeZoneConfig{
			DefaultTimeZone:  "UTC",
			DatabaseTimeZone: "UTC",
			DisplayTimeZone:  "Asia/Hong_Kong", // 默认显示香港时间
		}
	}

	// 验证时区是否有效
	if err := ValidateTimeZone(config.DefaultTimeZone); err != nil {
		return fmt.Errorf("invalid default timezone: %v", err)
	}
	if err := ValidateTimeZone(config.DatabaseTimeZone); err != nil {
		return fmt.Errorf("invalid database timezone: %v", err)
	}
	if err := ValidateTimeZone(config.DisplayTimeZone); err != nil {
		return fmt.Errorf("invalid display timezone: %v", err)
	}

	GlobalTimeZone = config
	return nil
}

// ValidateTimeZone 验证时区是否有效
func ValidateTimeZone(timezone string) error {
	_, err := time.LoadLocation(timezone)
	return err
}

// GetTimeZone 获取时区配置
func GetTimeZone() *TimeZoneConfig {
	if GlobalTimeZone == nil {
		// 返回默认配置
		return &TimeZoneConfig{
			DefaultTimeZone:  "UTC",
			DatabaseTimeZone: "UTC",
			DisplayTimeZone:  "Asia/Hong_Kong",
		}
	}
	return GlobalTimeZone
}

// Now 获取当前时间（使用默认时区）
func Now() time.Time {
	config := GetTimeZone()
	loc, err := time.LoadLocation(config.DefaultTimeZone)
	if err != nil {
		// 如果加载失败，使用UTC
		return time.Now().UTC()
	}
	return time.Now().In(loc)
}

// NowUTC 获取当前UTC时间
func NowUTC() time.Time {
	return time.Now().UTC()
}

// NowInDisplay 获取当前显示时区时间
func NowInDisplay() time.Time {
	config := GetTimeZone()
	loc, err := time.LoadLocation(config.DisplayTimeZone)
	if err != nil {
		return time.Now().UTC()
	}
	return time.Now().In(loc)
}

// ParseTime 解析时间字符串（支持多种格式）
func ParseTime(timeStr string) (time.Time, error) {
	config := GetTimeZone()
	loc, err := time.LoadLocation(config.DefaultTimeZone)
	if err != nil {
		loc = time.UTC
	}

	// 尝试多种时间格式
	formats := []string{
		"2006-01-02 15:04:05",
		"2006-01-02T15:04:05Z",
		"2006-01-02T15:04:05.000Z",
		"2006-01-02",
		"2006/01/02 15:04:05",
		"2006/01/02",
		time.RFC3339,
		time.RFC3339Nano,
	}

	for _, format := range formats {
		if t, err := time.ParseInLocation(format, timeStr, loc); err == nil {
			return t, nil
		}
	}

	return time.Time{}, fmt.Errorf("unable to parse time string: %s", timeStr)
}

// ParseTimeInZone 在指定时区解析时间
func ParseTimeInZone(timeStr, timezone string) (time.Time, error) {
	loc, err := time.LoadLocation(timezone)
	if err != nil {
		return time.Time{}, fmt.Errorf("invalid timezone %s: %v", timezone, err)
	}

	formats := []string{
		"2006-01-02 15:04:05",
		"2006-01-02T15:04:05Z",
		"2006-01-02T15:04:05.000Z",
		"2006-01-02",
		"2006/01/02 15:04:05",
		"2006/01/02",
		time.RFC3339,
		time.RFC3339Nano,
	}

	for _, format := range formats {
		if t, err := time.ParseInLocation(format, timeStr, loc); err == nil {
			return t, nil
		}
	}

	return time.Time{}, fmt.Errorf("unable to parse time string: %s", timeStr)
}

// FormatTime 格式化时间为字符串
func FormatTime(t time.Time, format string) string {
	return t.Format(format)
}

// FormatTimeDisplay 格式化时间为显示时区
func FormatTimeDisplay(t time.Time, format string) string {
	config := GetTimeZone()
	loc, err := time.LoadLocation(config.DisplayTimeZone)
	if err != nil {
		return t.Format(format)
	}
	return t.In(loc).Format(format)
}

// FormatTimeUTC 格式化时间为UTC
func FormatTimeUTC(t time.Time, format string) string {
	return t.UTC().Format(format)
}

// ConvertTimeZone 转换时区
func ConvertTimeZone(t time.Time, fromZone, toZone string) (time.Time, error) {
	fromLoc, err := time.LoadLocation(fromZone)
	if err != nil {
		return time.Time{}, fmt.Errorf("invalid from timezone %s: %v", fromZone, err)
	}

	toLoc, err := time.LoadLocation(toZone)
	if err != nil {
		return time.Time{}, fmt.Errorf("invalid to timezone %s: %v", toZone, err)
	}

	// 先转换到UTC，再转换到目标时区
	utcTime := t.In(fromLoc).UTC()
	return utcTime.In(toLoc), nil
}

// GetTimeZoneOffset 获取时区偏移量（小时）
func GetTimeZoneOffset(timezone string) (int, error) {
	loc, err := time.LoadLocation(timezone)
	if err != nil {
		return 0, err
	}

	_, offset := time.Now().In(loc).Zone()
	return offset / 3600, nil
}

// IsBusinessHours 判断是否为营业时间（9:00-18:00）
func IsBusinessHours(t time.Time, timezone string) bool {
	loc, err := time.LoadLocation(timezone)
	if err != nil {
		return false
	}

	localTime := t.In(loc)
	hour := localTime.Hour()

	// 判断是否为工作日（周一到周五）
	weekday := localTime.Weekday()
	if weekday == time.Saturday || weekday == time.Sunday {
		return false
	}

	// 判断是否为营业时间（9:00-18:00）
	return hour >= 9 && hour < 18
}

// GetBusinessDayStart 获取营业日开始时间
func GetBusinessDayStart(t time.Time, timezone string) time.Time {
	loc, err := time.LoadLocation(timezone)
	if err != nil {
		return t
	}

	localTime := t.In(loc)
	year, month, day := localTime.Date()
	return time.Date(year, month, day, 9, 0, 0, 0, loc)
}

// GetBusinessDayEnd 获取营业日结束时间
func GetBusinessDayEnd(t time.Time, timezone string) time.Time {
	loc, err := time.LoadLocation(timezone)
	if err != nil {
		return t
	}

	localTime := t.In(loc)
	year, month, day := localTime.Date()
	return time.Date(year, month, day, 18, 0, 0, 0, loc)
}

// GetNextBusinessDay 获取下一个营业日
func GetNextBusinessDay(t time.Time, timezone string) time.Time {
	loc, err := time.LoadLocation(timezone)
	if err != nil {
		return t
	}

	nextDay := t.AddDate(0, 0, 1)
	for nextDay.Weekday() == time.Saturday || nextDay.Weekday() == time.Sunday {
		nextDay = nextDay.AddDate(0, 0, 1)
	}

	year, month, day := nextDay.Date()
	return time.Date(year, month, day, 9, 0, 0, 0, loc)
}

// FormatDuration 格式化持续时间
func FormatDuration(d time.Duration) string {
	if d < time.Minute {
		return fmt.Sprintf("%.0fs", d.Seconds())
	}
	if d < time.Hour {
		return fmt.Sprintf("%.0fm", d.Minutes())
	}
	if d < 24*time.Hour {
		return fmt.Sprintf("%.0fh", d.Hours())
	}
	return fmt.Sprintf("%.0fd", d.Hours()/24)
}

// GetTimeZoneAbbr 获取时区缩写
func GetTimeZoneAbbr(timezone string) string {
	abbrMap := map[string]string{
		"UTC":                 "UTC",
		"GMT":                 "GMT",
		"America/New_York":    "EST",
		"America/Los_Angeles": "PST",
		"Asia/Shanghai":       "CST",
		"Asia/Hong_Kong":      "HKT",
		"Asia/Singapore":      "SGT",
		"Asia/Tokyo":          "JST",
		"Asia/Seoul":          "KST",
		"Asia/Kolkata":        "IST",
		"Europe/London":       "WET",
		"Europe/Paris":        "CET",
		"Europe/Athens":       "EET",
		"Europe/Moscow":       "MSK",
		"Africa/Johannesburg": "SAST",
		"Australia/Sydney":    "AEST",
		"Pacific/Auckland":    "NZST",
	}

	if abbr, exists := abbrMap[timezone]; exists {
		return abbr
	}
	return timezone
}
